package com.rules.admin.unit.mock;

import com.gillion.grule.client.core.ComponentHolder;
import com.gillion.grule.client.core.Context;
import com.gillion.grule.client.core.ExecuteComponent;
import com.gillion.grule.client.logger.LoggerAppenderHolder;
import com.google.common.collect.Maps;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

public class ComponentMock implements Mock {
   private String mockComponent;
   private String mockExpression;
   private Object mockValue;
   private static final ThreadLocal<Map<String, ExecuteComponent>> MOCK_COMPONENTS = new ThreadLocal();
   private static final ThreadLocal<Map<String, ExecuteComponent>> EXECUTE_COMPONENTS = new ThreadLocal();
   private static final Logger LOGGER = LoggerFactory.getLogger(ComponentMock.class);

   public void mock(Context context) {
      ExecuteComponent component;
      if (!getMockComponents().containsKey(this.mockComponent)) {
         component = ComponentHolder.getComponent(this.mockComponent);
         if (component != null) {
            component = (ExecuteComponent)Mockito.mock(component.getClass());
            getMockComponents().put(this.mockComponent, component);
         }
      }

      component = (ExecuteComponent)getMockComponents().get(this.mockComponent);
      save(this.mockComponent, component);
      Mockito.when(component.execute(this.mockExpression, context)).then(new Answer<Object>() {
         public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
            LoggerAppenderHolder.log("Mock组件执行，mock组件为：{}，表达式为：{}，返回值为：{}", new Object[]{ComponentMock.this.mockComponent, ComponentMock.this.mockExpression, ComponentMock.this.mockValue});
            return ComponentMock.this.mockValue;
         }
      }).thenReturn(this.mockValue);
   }

   public static Map<String, ExecuteComponent> getMockComponents() {
      if (MOCK_COMPONENTS.get() != null) {
         return (Map)MOCK_COMPONENTS.get();
      } else {
         Map<String, ExecuteComponent> componentMap = Maps.newConcurrentMap();
         MOCK_COMPONENTS.set(componentMap);
         return (Map)MOCK_COMPONENTS.get();
      }
   }

   public static ExecuteComponent getMockComponent(String component) {
      return getMockComponents().get(component);
   }

   public static void save(String name, ExecuteComponent component) {
      Map<String, ExecuteComponent> componentMap = Maps.newConcurrentMap();
      EXECUTE_COMPONENTS.set(componentMap);
      ((Map)EXECUTE_COMPONENTS.get()).put(name, component);
   }

   public static ExecuteComponent getComponent(String name) {
      return (ExecuteComponent)((Map)EXECUTE_COMPONENTS.get()).get(name);
   }

   public String getMockComponent() {
      return this.mockComponent;
   }

   public String getMockExpression() {
      return this.mockExpression;
   }

   public Object getMockValue() {
      return this.mockValue;
   }

   public void setMockComponent(String mockComponent) {
      this.mockComponent = mockComponent;
   }

   public void setMockExpression(String mockExpression) {
      this.mockExpression = mockExpression;
   }

   public void setMockValue(Object mockValue) {
      this.mockValue = mockValue;
   }

   public boolean equals(Object o) {
      if (o == this) {
         return true;
      } else if (!(o instanceof ComponentMock)) {
         return false;
      } else {
         ComponentMock other = (ComponentMock)o;
         if (!other.canEqual(this)) {
            return false;
         } else {
            label47: {
               Object this$mockComponent = this.getMockComponent();
               Object other$mockComponent = other.getMockComponent();
               if (this$mockComponent == null) {
                  if (other$mockComponent == null) {
                     break label47;
                  }
               } else if (this$mockComponent.equals(other$mockComponent)) {
                  break label47;
               }

               return false;
            }

            Object this$mockExpression = this.getMockExpression();
            Object other$mockExpression = other.getMockExpression();
            if (this$mockExpression == null) {
               if (other$mockExpression != null) {
                  return false;
               }
            } else if (!this$mockExpression.equals(other$mockExpression)) {
               return false;
            }

            Object this$mockValue = this.getMockValue();
            Object other$mockValue = other.getMockValue();
            if (this$mockValue == null) {
               if (other$mockValue != null) {
                  return false;
               }
            } else if (!this$mockValue.equals(other$mockValue)) {
               return false;
            }

            return true;
         }
      }
   }

   protected boolean canEqual(Object other) {
      return other instanceof ComponentMock;
   }

   public int hashCode() {

      int result = 1;
      Object $mockComponent = this.getMockComponent();
      result = result * 59 + ($mockComponent == null ? 43 : $mockComponent.hashCode());
      Object $mockExpression = this.getMockExpression();
      result = result * 59 + ($mockExpression == null ? 43 : $mockExpression.hashCode());
      Object $mockValue = this.getMockValue();
      result = result * 59 + ($mockValue == null ? 43 : $mockValue.hashCode());
      return result;
   }

   public String toString() {
      return "ComponentMock(mockComponent=" + this.getMockComponent() + ", mockExpression=" + this.getMockExpression() + ", mockValue=" + this.getMockValue() + ")";
   }
}
